package com.example.month11.appupdate.updater.net;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;



// 网络请求接口，具体的实现类。可以有不同的N种实现类。
public class OkHttpNetManager implements INetManager {
    private static OkHttpClient sOkHttpClient;
    // 绑定UI线程。结果转发到UI线程。
    private static Handler sHandler = new Handler(Looper.getMainLooper());


    static {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(15, TimeUnit.SECONDS);
        // https自签名，okhttp握手的错误。builder.sslSocketFactory().
        sOkHttpClient = builder.build();
    }

    @Override
    public void get(String url, INetCallBack callBack, Object tag) {
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build();
        Call call = sOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String string = request.body().toString(); // string()
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.success(string);
                        }
                    });
                } catch (Throwable e) {
                    e.printStackTrace();
                    callBack.failed(e); // 异常传递
                }
            }
        });
    }

    @Override
    public void download(String url, File targetFile, INetDownloadCallBack callBack, Object tag) {
        if (!targetFile.exists()) { // 先创建文件夹
            targetFile.getParentFile().mkdirs();
        }
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(url).get().tag(tag).build(); // 绑定tag
        Call call = sOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.failed(e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                OutputStream os = null;
                try {
                    // 文件下载。
                    is = response.body().byteStream(); // 输入流
                    os = new FileOutputStream(targetFile); // 输出流

                    long totalLen = response.body().contentLength();
                    byte[] buffer = new byte[8 * 1024]; // 8K缓存数组
                    long curLen = 0; // 当前写了多少个直接，用于计算下载百分比。
                    int bufferLen = 0;
                    // 确保上报progress的时候，请求一定是没有取消的。
                    while (!call.isCanceled() && (bufferLen = is.read(buffer)) != -1) {
                        os.write(buffer, 0, bufferLen);
                        os.flush();
                        curLen += bufferLen;

                        long finalCurLen = curLen;
                        sHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                // 下载百分比。
                                callBack.progress((int) (finalCurLen * 1.0f / totalLen * 100));
                            }
                        });
                    }
                    if (call.isCanceled()) return;

                    // 可执行，可读可写
                    targetFile.setExecutable(true, false);
                    targetFile.setReadable(true, false);
                    targetFile.setWritable(true, false);

                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            // 下载完成
                            callBack.success(targetFile);
                        }
                    });
                } catch (Throwable e) {
                    if (call.isCanceled()) return; // 取消的网络请求，直接return。
                    // 下载出错。
                    e.printStackTrace();
                    sHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.failed(e);
                        }
                    });
                } finally {
                    if (is != null) {
                        is.close();
                    }
                    if (os != null) {
                        os.close();
                    }
                }

            }
        });
    }

    @Override
    public void cancel(Object tag) {
        // 根据tag，取消call
        // 排队中的请求
        List<Call> queuedCalls = sOkHttpClient.dispatcher().queuedCalls();
        if (queuedCalls != null) {
            for (Call call : queuedCalls) {
                Log.d("tag", "find the call:" + tag);
                call.cancel(); // 取消网络请求
            }
        }
        // 正在执行的。
        List<Call> runningCalls = sOkHttpClient.dispatcher().runningCalls();
        if (runningCalls != null) {
            for (Call call : runningCalls) {
                Log.d("tag", "find the call:" + tag);
                call.cancel(); // 取消网络请求
            }
        }
    }
}
